

import Foundation
import Alamofire

// MARK: - 域名管理核心
class DynamicDomainManager {
    static let shared = DynamicDomainManager()
    
    // 初始配置域名
    private let bootstrapDomain = "https://testapp.macrobullion.net"
    // 当前域名池
    private(set) var apiDomains: [String] = ["https://app.macrobullion.net", "https://app.cigws.com", "https://app.jishich.cn"]
    private(set) var socketDomains: [String] = ["ws://112.121.161.67:10095","ws://112.121.161.67:10096"]
    
    // 域名健康状态
    private var domainHealth: [String: Bool] = [:]
    private var domainWeights: [String: Double] = [:]
    private let lock = NSLock()
    
    // 配置过期时间
    private var configExpires: Date?
    
    private init() {
        loadCachedConfig()
    }
    
    private func loadCachedConfig() {
        guard let cache = UserDefaults.standard.dictionary(forKey: "DomainConfig"),
              let apiDomains = cache["apiDomains"] as? [String],
              let socketDomains = cache["socketDomains"] as? [String],
              let expires = cache["expires"] as? Date,
              expires > Date() else {
            return
        }
        
        self.apiDomains = apiDomains
        self.socketDomains = socketDomains
        self.configExpires = expires
        
        // 重置健康状态
        apiDomains.forEach {
            domainHealth[$0] = true
            domainWeights[$0] = 1.0
        }
    }
}

extension DynamicDomainManager {
    // MARK: 配置管理 - 从服务器拉取多域名：apis & sockets
    func fetchInitialConfig(completion: @escaping (Result<Bool, APIError>) -> Void) {
        // 检查缓存是否有效
        if let expires = configExpires, expires > Date() {
            completion(.success(true))
            return
        }
        
        let url = "\(bootstrapDomain)/v1/auth/connected"
        
        AF.request(url,
                   method: .get,
                   requestModifier: { $0.timeoutInterval = 5.0 })
        .responseData { response in
            switch response.result {
                case .success(let configResponse):
                    debugPrint("请求成功")
                    self.updateDomains(
                        api: self.apiDomains/*configResponse.data.apiEndpoints*/,
                        socket: self.socketDomains/*configResponse.data.socketEndpoints*/
                    )
                    self.configExpires = Date().addingTimeInterval(/*configResponse.data.ttl*/TimeInterval.infinity)
                    self.cacheConfig()
                    completion(.success(true))

                case .failure(let error):
                    debugPrint("请求失败: \(error.localizedDescription)")
                    // 尝试使用缓存配置
                    if !self.apiDomains.isEmpty {
                        completion(.success(true))
                    } else {
                        completion(.failure(.networkError(error)))
                    }
            }
        }
//        AF.request(url).validate().responseDecodable(of: APIResponse<ServerConfig>.self) { [weak self] response in
//            guard let self = self else { return }
//            
//            switch response.result {
//                case .success(let configResponse):
//                    /// 更新缓存的域名池
//                    self.updateDomains(
//                        api: configResponse.data.apiEndpoints,
//                        socket: configResponse.data.socketEndpoints
//                    )
//                    self.configExpires = Date().addingTimeInterval(configResponse.data.ttl)
//                    self.cacheConfig()
//                    completion(.success(true))
//                    
//                case .failure(let error):
//                    /// 尝试使用缓存配置
//                    if !self.apiDomains.isEmpty {
//                        completion(.success(true))
//                    } else {
//                        completion(.failure(.networkError(error)))
//                    }
//            }
//        }
    }
}

extension DynamicDomainManager {
    // MARK: 更新缓存的域名池
    private func updateDomains(api: [String], socket: [String]) {
        lock.lock()
        defer { lock.unlock() }
        
        apiDomains = api
        socketDomains = socket
        
        // MARK: 初始化健康状态和权重
        api.forEach {
            domainHealth[$0] = true
            domainWeights[$0] = 1.0
        }
    }
    
    // MARK: 域名健康管理
    func markDomainHealthy(_ domain: String) {
        lock.lock()
        defer { lock.unlock() }
        
        domainHealth[domain] = true
        domainWeights[domain] = min((domainWeights[domain] ?? 1.0) * 1.1, 1.0) // 增加权重
    }
    
    // MARK: 标记异常域名
    func markDomainUnhealthy(_ domain: String) {
        lock.lock()
        defer { lock.unlock() }
        
        domainHealth[domain] = false
        domainWeights[domain] = (domainWeights[domain] ?? 1.0) * 0.7 // 降低权重
        
        // 异步执行健康检查
        performHealthCheck(for: domain)
    }
    
    // MARK: 这里需要连接域名查看健康状态
    private func performHealthCheck(for domain: String) {
        let healthURL = "\(domain)/health"
        
        AF.request(healthURL, method: .head).response { [weak self] _ in
            // 30分钟后重置为健康状态
            DispatchQueue.main.asyncAfter(deadline: .now() + 1800) {
                self?.lock.lock()
                self?.domainHealth[domain] = true
                self?.lock.unlock()
            }
        }
    }
    
    // MARK: 域名选择策略
    func getOptimalAPIDomain() -> String? {
        lock.lock()
        defer { lock.unlock() }
        
        // 健康域名优先 + 权重选择
        let healthyDomains = apiDomains.filter { domainHealth[$0] ?? true }
        if !healthyDomains.isEmpty {
            return selectByWeight(domains: healthyDomains)
        }
        
        // 没有健康域名则尝试所有域名
        return selectByWeight(domains: apiDomains)
    }
    
    // MARK: 抽取socketDomains
    func getSocketDomains() -> [String] {
        lock.lock()
        defer { lock.unlock() }
        return socketDomains
    }
    
    // MARK: 选择权重更高的域名
    private func selectByWeight(domains: [String]) -> String? {
        let totalWeight = domains.reduce(0) { $0 + (domainWeights[$1] ?? 1.0) }
        let random = Double.random(in: 0..<totalWeight)
        
        var current: Double = 0
        for domain in domains {
            current += domainWeights[domain] ?? 1.0
            if random < current {
                return domain
            }
        }
        
        return domains.first
    }
    
    // MARK: 配置缓存
    private func cacheConfig() {
        guard !apiDomains.isEmpty, let expires = configExpires else { return }
        
        let cacheData: [String: Any] = [
            "apiDomains": apiDomains,
            "socketDomains": socketDomains,
            "expires": expires
        ]
        
        UserDefaults.standard.set(cacheData, forKey: "DomainConfig")
    }
    
}

